<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>xeokit Example</title>
    <link href="../css/pageStyle.css" rel="stylesheet"/>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/js/all.min.js"></script>

    <style>

        /* ----------------------------------------------------------------------------------------------------------*/
        /* NavCubePlugin */
        /* ----------------------------------------------------------------------------------------------------------*/

        #myNavCubeCanvas {
            position: absolute;
            width: 250px;
            height: 250px;
            bottom: 50px;
            right: 10px;
            z-index: 200000;
        }


    </style>
</head>
<body>
<input type="checkbox" id="info-button"/>
<label for="info-button" class="info-button"><i class="far fa-3x fa-question-circle"></i></label>
<canvas id="myCanvas"></canvas>
<canvas id="myNavCubeCanvas"></canvas>
<div class="slideout-sidebar">
    <img class="info-icon" src="../../assets/images/performance_model_icon.png"/>
    <h1>SceneModel</h1>
    <h2>Geometry batching and RTC coordinates</h2>
    <p>In this example, we're programmatically building a simple model using xeokit's SceneModel component, while
        at the same using a separate geometry for each object, and providing geometry vertex positions as
        relative-to-center (RTC) coordinates.</p>
    <p>RTC coordinates are xeokit's mechanism for full-precision emulation.</p>
    <h3>Components Used</h3>
    <ul>
        <li>
            <a href="../../docs/class/src/viewer/Viewer.js~Viewer.html"
               target="_other">Viewer</a>
        </li>
        <li>
            <a href="../../docs/class/src/viewer/scene/model/SceneModel.js~SceneModel.html"
               target="_other">SceneModel</a>
        </li>
    </ul>
</div>
</body>

<script type="module">

    //------------------------------------------------------------------------------------------------------------------
    // Import the modules we need for this example
    //------------------------------------------------------------------------------------------------------------------

    import {Viewer, SceneModel,NavCubePlugin, math} from "../../dist/xeokit-sdk.min.es.js";

    let geometryNum = 0;

    //------------------------------------------------------------------------------------------------------------------
    // Create a Viewer and arrange the camera
    //------------------------------------------------------------------------------------------------------------------

    const viewer = new Viewer({
        canvasId: "myCanvas",
        transparent: true,
        dtxEnabled: false,
        logarithmicDepthBuffer: true
    });

    viewer.scene.camera.eye = [+1000000000, 0,500];
    viewer.scene.camera.look = [+1000000000, 0,0];
    viewer.scene.camera.up = [0, 1,0];

    new NavCubePlugin(viewer, {
        canvasId: "myNavCubeCanvas",
        visible: true,
        size: 250,
        alignment: "bottomRight",
        bottomMargin: 100,
        rightMargin: 10
    });

    //------------------------------------------------------------------------------------------------------------------
    // Create a SceneModel representing a table with four legs, using geometry batching
    //------------------------------------------------------------------------------------------------------------------

    const sceneModel = new SceneModel(viewer.scene, {
        id: "tables",
        isModel: true,
        scale: [1, 1, 1],
        rotation: [0, 0, 0],
        edges: true
    });

    //-----------------------------------------------------------
    // Create several origin points
    //-----------------------------------------------------------

    const OFFSET = 7;

    const origins = [
        [-OFFSET, -OFFSET, -OFFSET],
        [+OFFSET, -OFFSET, -OFFSET],
        [-OFFSET, -OFFSET, +OFFSET],
        [+OFFSET, -OFFSET, +OFFSET]
    ];

    //-----------------------------------------------------------
    // Within out SceneModel, create a simple table model
    // at each of our origins. This will result in several
    // tables, positioned very far apart from each other.
    //-----------------------------------------------------------

    for (let i = 0, len = origins.length; i < len; i++) {
        buildTable(sceneModel, origins[i]);
    }

    //------------------------------------------------------------
    // Finalize the SceneModel.
    //------------------------------------------------------------

    sceneModel.finalize();



    //------------------------------------------------------------------------------------------------------------------
    // Creates a simple table-shaped model with the given SceneModel,
    // without reusing geometry, and centered at the given origin
    //------------------------------------------------------------------------------------------------------------------


    function buildTable(sceneModel, origin) {

        const geometryId = ("myBoxGeometry" + geometryNum++);

        sceneModel.createGeometry({
            id: geometryId,
            primitive: "triangles",
            positions: [
                1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1,
                1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1,
                -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1
            ],
            indices: [
                0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, 8, 9, 10, 8, 10, 11, 12, 13, 14, 12, 14, 15,
                16, 17, 18, 16, 18, 19, 20, 21, 22, 20, 22, 23
            ]
        });

        let meshId = math.createUUID();

        sceneModel.createMesh({
            id: meshId,
            origin: origin, // This mesh's positions and transforms are relative to the origin
            primitive: "triangles",
            geometryId,
            position: [-4, -6, -4],
            scale: [1, 3, 1],
            rotation: [0, 0, 0],
            color: [1, 0.3, 0.3]
        });

        sceneModel.createEntity({
            meshIds: [meshId],
            isObject: true
        });

        meshId = math.createUUID();

        sceneModel.createMesh({
            id: meshId,
            origin: origin,
            primitive: "triangles",
            geometryId,
            position: [4, -6, -4],
            scale: [1, 3, 1],
            rotation: [0, 0, 0],
            color: [0.3, 1.0, 0.3]
        });

        sceneModel.createEntity({
            meshIds: [meshId],
            isObject: true
        });

        meshId = math.createUUID();

        sceneModel.createMesh({
            id: meshId,
            origin: origin,
            geometryId,
            position: [4, -6, 4],
            scale: [1, 3, 1],
            rotation: [0, 0, 0],
            color: [0.3, 0.3, 1.0]
        });

        sceneModel.createEntity({
            meshIds: [meshId],
            isObject: true
        });

        meshId = math.createUUID();

        sceneModel.createMesh({
            id: meshId,
            origin: origin,
            geometryId,
            position: [-4, -6, 4],
            scale: [1, 3, 1],
            rotation: [0, 0, 0],
            color: [1.0, 1.0, 0.0]
        });

        sceneModel.createEntity({
            meshIds: [meshId],
            isObject: true
        });

        meshId = math.createUUID();

        sceneModel.createMesh({
            id: meshId,
            origin: origin,
            geometryId,
            position: [0, -3, 0],
            scale: [6, 0.5, 6],
            rotation: [0, 0, 0],
            color: [1.0, 0.3, 1.0]
        });

        sceneModel.createEntity({
            meshIds: [meshId],
            isObject: true
        });
    }

    const position = [1000000000, 0, 0];
    const rotation = [0, 0, 0];

    const next = () => {
        requestAnimationFrame(() => {

            sceneModel.position = position;
            sceneModel.rotation = rotation;

            position[0] += 1.1;

            rotation[1] += 0.1;
            rotation[2] += 0.4;

            if (position[0] < 1000000100) {
                next();
            }
        });
    }

    next();

    window.viewer = viewer; // For consle debugging

</script>
</html>